#pragma once
#include<iostream>
#include<algorithm>

template<class T>
class Shared_ptr
{
public:
	Shared_ptr(const T* ptr = nullptr) :_ptr(ptr), _count(new size_t(1))
	{
		if (ptr == nullptr)
			*(_count) = 0;
	}

	Shared_ptr(const Shared_ptr<T>& ptr) :_ptr(ptr._ptr), _count(ptr._count)
	{
		if (this != &ptr)
		{
			release();
			_ptr = ptr._ptr;
			_count = ptr._count;
			if(_ptr)
			++(*_count);
		}
	}
	Shared_ptr(Shared_ptr<T>&& ptr):_ptr(ptr._ptr),_count(ptr._count)
	{
		ptr._coun = nullptr;
		ptr._ptr = nullptr;
	}
	T* get() const{ return _ptr; }
	size_t use_count()const { return *_count; }
	Shared_ptr& operator=(Shared_ptr<T>&& ptr)
	{
		if (this != &ptr)
		{
			release();
			_ptr = ptr._ptr;
			_count = ptr._count;
		}
		ptr._ptr = nullptr;
		ptr._count = nullptr;
		return *this;
	}
	
	void reset(const T* ptr=nullptr)
	{
		release();
		_ptr = ptr;
		_count = new size_t(1);
		if (_ptr==nullptr)
			*_count = 0;
	}
	~Shared_ptr()
	{
		release();
	}
	T& operator*() { return *_ptr; }
	T* operator->() { return _ptr; }
private:
	void Swap(Shared_ptr<T>& ptr)
	{
		std::swap(_ptr, ptr._ptr);
		std::swap(_count, ptr._count);
	}

	void release()
	{
		if (_ptr && --(*_count) == 0)
		{
			delete _ptr;
			delete _count;
			_ptr = nullptr;
			_count == nullptr;
		}
	}
	T* _ptr;
	size_t* _count;
};